The present invention relates to the field of computer graphics. Many computer graphic images are created by mathematically modeling the interaction of light with a three dimensional scene from a given viewpoint. This process, called rendering, generates a two-dimensional image of the scene from the given viewpoint, and is analogous to taking a photograph of a real-world scene.
As the demand for computer graphics, and in particular for real-time computer graphics, has increased, computer systems with graphics processing subsystems adapted to accelerate the rendering process have become widespread. In these computer systems, the rendering process is divided between a computer's general purpose central processing unit (CPU) and the graphics processing subsystem. Typically, the CPU performs high level operations, such as determining the position, motion, and collision of objects in a given scene. From these high level operations, the CPU generates a set of rendering commands and data defining the desired rendered image or images. For example, rendering commands and data can define scene geometry, lighting, shading, texturing, motion, and/or camera parameters for a scene. The graphics processing subsystem creates one or more rendered images from the set of rendering commands and data.
Many graphics processing subsystems are highly programmable, enabling implementation of, among other things, complicated lighting and shading algorithms. In order to exploit this programmability, applications can include one or more graphics processing subsystem programs, which are executed by the graphics processing subsystem in parallel with a main program executed by the CPU. Although not confined to merely implementing shading and lighting algorithms, these graphics processing subsystem programs are often referred to as shader programs or shaders. Shader programs can be used to define a set of operations to be performed on object geometry, object vertices, and/or fragments, which are groups of pixels or subpixels.
In their most basic form, shader programs can be written in an assembly-like language specifically tailored to the graphics processing subsystem. Although this type of language allows for highly optimized shader programs, it is often cumbersome to use, requires detailed knowledge of the design of the graphics processing subsystem, and makes developing portable shader programs difficult, if not impossible. There are also high level shading-specific languages designed around abstract models of lighting and shading operations, such as Pixar's RenderMan. However, these shading-specific languages are intended for non-real-time rendering application and are typically too far removed from the underlying architecture of typical graphics processing subsystems to be used for real-time rendering applications.
To address these deficiencies, high level graphics processing subsystem languages, such as Nvidia's Cg, have been developed. High level graphics processing subsystem languages are designed around the general architecture of typical graphics processing subsystems. However, unlike assembly-type languages, high level graphics processing subsystem languages provide a large degree of abstraction, greatly simplifying the development of shader programs. Additionally, shader programs written with high level graphics processing subsystem languages can be easily made portable. Further, because the high level graphics processing subsystem language is designed around the general architecture of typical graphics processing subsystems, they are well-suited for implementing real-time rendering.
One difficulty with high-level graphics processing subsystem languages, high-level shading-specific languages, and even assembly-like graphics processing subsystem languages is the inability to dynamically combine two or more shader program components, referred to as subshaders, into a single shader program. Graphics processing subsystems typically lack the complex branching and indirection capabilities of typical CPUs, making conventional methods of combining programs, such as dynamic linking, impossible to implement.
Previously, developers could construct a monolithic shader program encompassing all of the possible combinations of subshaders. The graphics processing subsystem would then be instructed to skip over the unused portions of the program during execution. However, this solution results in a very large shader program that is difficult to modify or expand and inefficient to execute. Additionally, with this approach, all combinations of subshaders are required to be known in advance. Alternatively, developers could enable their application to dynamically generate code for a desired combination of subshaders on the fly. However, this approach is difficult to implement and error-prone.
It is therefore desirable for a graphics processing subsystem to facilitate the composition of shader programs from two or more modular subshaders. It is also desirable for the graphics processing subsystem to enable the creation of new shader programs dynamically and without advance knowledge of the desired combination of subshaders or the specific limitations of the graphics processing subsystem. The ability to easily add additional subshaders is another desired feature of a graphics processing subsystem. It is further desirable that the resulting shader program executes efficiently and does not include large amounts of unexecuted code.